%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2020, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 08. 1月 2020 11:35
%%%-------------------------------------------------------------------
-module(game_assist).
-author("Administrator").
-include("../include/protocol.hrl").
-include("../include/myshare.hrl").
-include("../include/player.hrl").
-include("../include/logger.hrl").
-include("../include/game.hrl").

%% API
-export([profit_calculation/2, threshold/2, random_msg/0, delete_room/2, bet_algorithm/2, bet_type_money/3,
  get_Into_integral/1, get_player_room_data/2, delete_player_room/2, get_task_info/1, get_player_room_ids/1
  , insert_player_into_room/2, get_player_into_room/1, delete_task/1, integral/1
  , add_room_seat/3, delete_room_seat/2, get_room_index/3,
  weiniu_bet_money/2, get_player_index/2, get_weiniu_zj/1, update_ets_task/1, take_min_integral/2,
  get_take_integral_num/1, get_task_condition/1, player_is_look_bet/2, task_limited/1]).

%%进入房间获取围牛庄家
-spec get_weiniu_zj(Players :: list()) -> {0|binary(), 0|integer()}.
get_weiniu_zj(Players) ->
  lists:foldl(
    fun(Player, Acc) ->
      case maps:get(isZhuangJia, Player) of
        true ->
          Id = maps:get(id, Player),
          Index = maps:get(index, Player),
          {Id, Index};
        _ -> Acc
      end
    end, {0, 0}, Players).

get_room_index(Players, PlayerId, GameId) ->
  Player_index =
    lists:foldl(
      fun(Player, Acc) ->
        Index = maps:get(index, Player),
        Id = maps:get(id, Player),
        case Id of
          PlayerId -> Index;
          _ ->
            Acc
        end
      end,
      undefined, Players),
  case Player_index of
    undefined ->
      Seats =
        case GameId of
          ?WEI_NIU ->
            [0, 1, 2, 3];
          ?NIU_NIU_MING_PAI ->
            [0, 1, 2, 3, 4, 5, 6, 7];
          _ ->
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        end,

      Indexs =
        lists:foldl(
          fun(Player, Acc) ->
            Index = maps:get(index, Player),
            [Index | Acc]
          end,
          [], Players),
      case length(Indexs) >= length(Seats) of
        true -> undefined;
        _ ->
          IndexList = sys_util:do2(Seats -- Indexs),
          erlang:hd(IndexList)
      end;
    _ -> Player_index
  end.

%%更新房间座位
add_room_seat(RoomId, Index, PlayerId) ->
  ?DEBUG("add_room_seat roomid:~p;index:~p;playerid:~p", [RoomId, Index, PlayerId]),
  case get_room_info(RoomId) of
    [] -> ok;
    RoomSeat ->
      ?DEBUG("add_room_seat roomseat :~p", [RoomSeat]),
      PlayerSeats = RoomSeat#room_seat_info.player_seats,
      NewMaps =
        maps:fold(
          fun(K, V, Acc) ->
            case maps:get(id, V) of
              PlayerId -> Acc;
              _ -> maps:put(K, V, Acc)
            end
          end, #{}, PlayerSeats),
      Seats =
        case maps:is_key(Index, NewMaps) of
          true ->
            maps:update(Index, #{index => Index, id => PlayerId}, NewMaps);
          _ -> maps:put(Index, #{index => Index, id => PlayerId}, NewMaps)
        end,
      ?DEBUG("add_room_seat ret :~p", [Seats]),
      ets:update_element(?ETS_ROOM_SEAT, RoomId, {#room_seat_info.player_seats, Seats})
  end.

%%删除房间座位
delete_room_seat(RoomId, PlayerId) ->
  case get_room_info(RoomId) of
    [] -> ok;
    RoomSeat ->
      PlayerSeats = RoomSeat#room_seat_info.player_seats,
      ?DEBUG("playerseats:~p,id:~p", [PlayerSeats, PlayerId]),
      case PlayerSeats =:= #{} orelse PlayerSeats =:= undefined of
        true -> ok;
        _ ->
          NewMaps =
            maps:fold(
              fun(K, V, Acc) ->
                case maps:get(id, V) of
                  PlayerId -> Acc;
                  _ -> maps:put(K, V, Acc)
                end
              end, #{}, PlayerSeats),
          ?DEBUG("delete_room_seat ret:~p", [NewMaps]),
          ets:update_element(?ETS_ROOM_SEAT, RoomId, {#room_seat_info.player_seats, NewMaps})
      end

  end.

get_room_info(RoomId) ->
  case ets:lookup(?ETS_ROOM_SEAT, RoomId) of
    [] -> [];
    [RoomSeat] -> RoomSeat
  end.

%%根据玩家id获取房间座位号
get_player_index(RoomId, PlayerId) ->
  case get_room_info(RoomId) of
    [] -> 0;
    RoomSeat ->
      Player_seats = RoomSeat#room_seat_info.player_seats,
      Index = maps:fold(
        fun(K, V, Acc) ->
          Id = maps:get(id, V, 0),
          case PlayerId of
            Id -> K;
            _ -> Acc
          end

        end, 0, Player_seats),
      Index
  end.


%%一局盈亏计算{余额,盈亏金额}
-spec profit_calculation(PlayerId :: string(), Data :: term()) -> {LeftScore :: float(), Score :: float()}.
profit_calculation(PlayerId, Data) ->
  PlayerResult = maps:get(playerResult, Data),
  Score2 = maps:get(list_to_atom(PlayerId), PlayerResult, 0),
  case Score2 of
    0 -> {0, 0};
    _ ->
      #{leftScore := LeftScore, score := Score} = Score2,
      {LeftScore, Score}
  end.

%%盈亏任务是否完成计算
-spec threshold(Threshold :: float(), Profit :: float()) -> boolean().
threshold(Threshold, Profit) ->
  if
    Threshold > 0 ->
      if
        Profit >= Threshold -> true;
        true -> false
      end;
    true ->
      if
        Threshold >= Profit -> true;
        true -> false
      end
  end.

%%取随机表情和常用语
-spec random_msg() -> integer()| no_return().
random_msg() ->
  case sys_util:random(50) of
    1 ->
      ?NIUNIU_EMOJI;
    2 ->
      %常用语
      ?NIUNIU_DAILY_MSG;
    _ -> normal
  end.

%%任务完成后取下一个房间
-spec delete_room(Account :: string(), RoomId :: integer()) -> room_data_list().
delete_room(Account, RoomId) ->
  ?DEBUG("delete roomid :~p", [RoomId]),
  case ets:lookup(?ETS_ROOM_INFO, Account) of
    [] -> [];
    [Room] ->
      %删除已完成的房间
      RoomList = lists:foldl(
        fun(R, Acc2) ->
          case R#room_data.room_id of
            RoomId -> Acc2;
            _ -> [R | Acc2]
          end
        end,
        [], Room#room_info.room_list),
      ?DEBUG("delete roominfo:~p,delete_room_id:~p", [RoomList, RoomId]),
      ets:update_element(?ETS_ROOM_INFO, Account, {#room_info.room_list, lists:keysort(#room_data.create_date, RoomList)}),
      RoomList
  end.
%%获取某个玩家所有房间ID集合
get_player_room_ids(Account) ->
  case ets:lookup(?ETS_ROOM_INFO, Account) of
    [] -> [];
    [Rooms] ->
      lists:foldl(
        fun(Room, Acc) ->
          RoomId = Room#room_data.room_id,
          [RoomId | Acc]
        end, [], Rooms#room_info.room_list)
  end.

%%押注算法，押注时间，上盘输赢绝对值
bet_algorithm(Mins, Plate) ->
  BetList =
    case Plate of
      0 ->
        [{Mins, ?TENTH}];
      _ ->
        case random_bet_type(fasle) of
          ?SAIL -> [{Mins, ?SAIL}];
          R1 ->
            RList = [{Mins, R1}],
            if
              Mins > 12 ->
                ?INFO("3 bets"),
                generate(2, Mins, RList);

              Mins > 8 andalso Mins < 12 ->
                ?INFO("2 bets"),
                generate(1, Mins, RList);
              true ->
                ?INFO("1 bets"),
                RList
            end
        end
    end,
  lists:keysort(1, BetList).

%%生成押注金额列表
generate(Num, Mins, List) ->
  if
    Num =:= 0 -> List;
    Mins < 5 -> List;
    true ->
      Num2 = Num - 1,
      OneTime = random_number:generate_random(Mins),
      One = random_bet_type(true),
      List2 = [
        {OneTime, One}
      ],
      List3 = List ++ List2,
      generate(Num2, OneTime, List3)
  end.

%%押注类型概率
random_bet_type(NotSail) ->
  RandomNum = random_number:generate_random(14),
  RandomNum2 = random_number:generate_random(100),
  case RandomNum2 of
    50 ->
      case NotSail of
        true -> random_bet_type(NotSail);
        _ -> ?SAIL
      end;
    _ ->
      case RandomNum rem 9 of
        1 -> ?PLATE;
        0 -> ?DOUBLE_PLATE;
        9 -> ?OTHER_MONEY;
        _ -> ?TENTH
      end
  end.


%%根据押注类型取金额
bet_type_money(Type, Plate, Left_score) ->
  Plate2 = round(Plate),
  Left_score2 = round(Left_score),
  Tenth = Left_score2 div 10,
  case Type of
    ?PLATE -> Plate2;
    ?DOUBLE_PLATE -> 2 * Plate2;
    ?TENTH -> Tenth - Tenth rem 10;
    _ ->
      Number = sys_util:interval_random_number(Tenth, Left_score2 div 5),
      Number - Number rem 10
  end.

get_task_info(TaskId) ->
  case ets:lookup(?ETS_GAME_TASK, TaskId) of
    [] -> [];
    [TaskInfo] -> TaskInfo
  end.

%%检查是否旁观玩家
-spec(player_is_look_bet(Task_id :: integer(), Account :: string()) -> boolean()).
player_is_look_bet(Task_id, Account) ->
  Task_info = get_task_info(Task_id),
  Player_list = Task_info#game_task.player_list,
  ?DEBUG("player_is_look_bet player_list:~p", [Player_list]),
  Game_task_player = lists:keyfind(Account, 3, Player_list),
  Game_task_player#game_task_player.is_look_bet.

%%获取任务带入积分次数
-spec(get_take_integral_num(Task_id :: integer()) -> integer()).
get_take_integral_num(Task_id) ->
  Task_info = get_task_info(Task_id),
  case Task_info of
    [] -> 0;
    _ -> Task_info#game_task.take_number
  end.

%%获取任务输赢条件
-spec(get_task_condition(Task_id :: integer()) -> integer()).
get_task_condition(Task_id) ->
  case get_task_info(Task_id) of
    [] -> 1000;
    Task_info -> Task_info#game_task.condition
  end.

%%获取带入积分
-spec(get_Into_integral(Room_status :: #room_status{}) -> integer()).
get_Into_integral(#room_status{account = Account, room_id = Room_id, left_score = Score, task_id = Task_id}) ->
  AllowIntegral = take_min_integral(Account, Room_id),%最低带入积分
  Task_into_integral = get_task_take_integral(Task_id),
  %有任务积分带入任务积分，否则带入最低入桌积分
  ?DEBUG("get_Into_integral AllowIntegral :~p;", [AllowIntegral]),
  Task_into_integral2 =
    case Task_into_integral of
      0 -> sys_util:interval_random_number(AllowIntegral * 1.5, AllowIntegral * 3);
      _ -> Task_into_integral
    end,
  case Task_into_integral2 > AllowIntegral of
    true -> Task_into_integral2;
    _ ->
      case Score >= AllowIntegral of
        true -> AllowIntegral;
        _ -> Score
      end
  end.


%%房间最低带入积分
take_min_integral(Account, Room_Id) ->
  case game_assist:get_player_room_data(Account, Room_Id) of
    #room_data{allow_integral = Allow} -> Allow;
    _ -> 600
  end.

%%任务带入随机积分
-spec(get_task_take_integral(Task_id :: integer()) -> integer()).
get_task_take_integral(Task_id) ->
  TaskInfo = get_task_info(Task_id),
  Start_num = TaskInfo#game_task.take_start_num,
  End_num = TaskInfo#game_task.take_end_num,
  sys_util:interval_random_number(Start_num, End_num).

%获取某个账号的所有房间信息
get_player_roomInfo(Account) ->
  case ets:lookup(?ETS_ROOM_INFO, Account) of
    [] -> [];
    [RoomInfo] -> RoomInfo#room_info.room_list
  end.

%获取某个账号的某个房间信息
get_player_room_data(Account, RoomId) ->
  case get_player_roomInfo(Account) of
    [] -> [];
    RoomList -> lists:keyfind(RoomId, 4, RoomList)
  end.

%删除房间数据
delete_player_room(Account, RoomId) ->
  case get_player_roomInfo(Account) of
    [] -> ok;
    RoomList ->
      NewRoom = lists:keydelete(RoomId, 4, RoomList),
      ets:update_element(?ETS_ROOM_INFO, Account, {#room_info.room_list, lists:keysort(#room_data.create_date, NewRoom)})
  end.


%%记录玩家已经进入的房间
insert_player_into_room(Account, RoomId) ->
  ?DEBUG("insert_player_into_room account:~p;roomid:~p", [Account, RoomId]),
  case get_player_into_room(Account) of
    [] ->
      ets:insert(?ETS_PLAYER_INTO_ROOM, #player_into_room{account = Account, rooms = [RoomId]});
    Rooms ->
      case lists:member(RoomId, Rooms) of
        true -> ok;
        _ -> NewRooms = [RoomId | Rooms],
          ets:update_element(?ETS_PLAYER_INTO_ROOM, Account, {#player_into_room.rooms, NewRooms})
      end
  end.
%%获取玩家已经进入的房间
get_player_into_room(Account) ->
  RoomInfo = ets:lookup(?ETS_PLAYER_INTO_ROOM, Account),
  ?DEBUG("get_player_into_room roomInfo:~p", [RoomInfo]),
  case RoomInfo of
    [] -> [];
    [RoomData] ->
      RoomData#player_into_room.rooms
  end.

%%删除任务玩家
delete_task(Task_Id) ->
  case game_assist:get_task_info(Task_Id) of
    [] -> ok;
    #game_task{player_list = Players} ->
      Fun2 = fun(#game_task_player{account = Account}) ->
        Pid = list_to_atom("pid_" ++ Account),
        ?INFO("player logout pid:~p ", [Pid]),
        Pid ! {kicking}
             end,
      lists:foreach(Fun2, Players)
  end.


%%积分转整数
integral(Num) ->
  if
    is_float(Num) -> Num2 = round(Num);
    is_list(Num) -> Num2 = list_to_integer(Num);
    true -> Num2 = Num
  end,
  if
    Num2 > 10 -> Num2 - (Num2 rem 10);
    true -> 100
  end.

%%围牛下注金额
-spec weiniu_bet_money(
    ZZ_money :: number(),%房间坐庄数量
    Number :: number()%上局结算后的底池数量
) -> {integer(), integer()}.
weiniu_bet_money(ZZ_money2, Number2) ->
  ZZ_money =
    case is_float(ZZ_money2) of
      true -> round(ZZ_money2);
      _ -> ZZ_money2
    end,
  Number =
    case is_float(Number2) of
      true -> round(Number2);
      _ -> Number2
    end,
  Type =
    case sys_util:random(6) of
      1 -> 22;
      _ -> 0
    end,
  Min_Money = ZZ_money div 5,
  Max_Money = Number div 2,
  case Number < Min_Money of
    true -> {Type, Min_Money};
    _ ->
      Number3 =
        case Number > Max_Money of
          true -> Max_Money;
          _ -> Number
        end,
      Money = sys_util:interval_random_number(Min_Money, Number3),
      Money2 = Money + (10 - (Money rem 10)),
      {Type, Money2}
  end.

%%修改ETS任务数据
-spec(update_ets_task(Task_id :: integer()) -> ok).
update_ets_task(Task_id) ->
  case game_assist:get_task_info(Task_id) of
    [] -> ok;
    _Task_info ->
      Rows = database:select_task(Task_id),
      case Rows of
        [] -> ok;
        [Row] ->
          [_Id, _Name, GameId, Player_number, Condition, Take_number, All_day_run, _Look_number, {_, Start_at},
            {_, End_at}, Start_number, End_number] = Row,
          Is_all_day_run =
            case All_day_run of
              1 -> true;
              _ -> false
            end,
          GameList = sys_util:json_to_list(GameId),
          Start_s = sys_util:datetime_to_timestamp(sys_util:time_to_date_time(Start_at)),
          End_ats = sys_util:datetime_to_timestamp(sys_util:time_to_date_time(End_at)),
          Task_info2 = [{#game_task.condition, Condition}, {#game_task.start_at, Start_s}, {#game_task.end_at, End_ats},
            {#game_task.take_start_num, Start_number}, {#game_task.take_end_num, End_number}, {#game_task.take_number, Take_number},
            {#game_task.player_number, Player_number}, {#game_task.gameId_list, GameList}, {#game_task.is_all_day_run, Is_all_day_run}],
          ets:update_element(?ETS_GAME_TASK, Task_id, Task_info2)
      end
  end,
  ok.

%%任务是否有效期内
task_limited(Task_id) ->
  case game_assist:get_task_info(Task_id) of
    [] -> false;
    #game_task{start_at = Start_at, end_at = End_at, is_all_day_run = Is_all_day_run} ->
      Now = sys_util:timestamp(),
      if
        Is_all_day_run =:= true -> true;
        Now > Start_at andalso End_at > (Now + 600) -> true;
        true -> false
      end
  end.












